(function ($) {

	/* tabs
	* 
	* Generic tabs object.
	*/
	orange.tabs = function (settings) {

		var _me = this,
			_container,
			_contentContainer,
			_tabs = {},
			_current = null;

		// Define default settings and extend them.
		var _settings = {
			container: null,
			classSelected: "selected",
			classRightLeft: "right-left",
			selectFirst: true
		};
		$.extend(_settings, settings);


		/*---------------------------------------------------------------------------------------------
		* Constants
		*--------------------------------------------------------------------------------------------*/

		/* init
		* 
		* Define the init method and initialize it immediately.
		*/
		function init() {

			_container = $(_settings.container);
			_contentContainer = _container.next(".tabs-content");

			// Hide all content.
			_contentContainer.children("LI").hide();

			// Is right-left design?
			var rightLeft = _container.hasClass(_settings.classRightLeft);

			var tabs = _container.children("LI"),
				first;

			tabs.each(function (index, element) {
				element = $(element);
				var anchor = element.find("A");
				var alias = anchor.data("tab");

				if (_settings.selectFirst && index === 0) {
					first = alias;
				}

				if (rightLeft) {
					anchor.append('<span class="left"></span><span class="right"></span>');
				}

				var content = _contentContainer.children("LI." + alias);

				// Attach click event to the tab link.
				element.bind("click", function () {
					_me.changeTab(alias);
				});

				// Create tab object.
				var tab = {
					'alias': alias,
					'element': element,
					'anchor': anchor,
					'content': content
				};

				_tabs[alias] = tab;

				// Mark as selected.
				if (element.hasClass(_settings.classSelected)) {
					_current = tab;
					_current.content.addClass(_settings.classSelected).show();
				}
			});
			if (first) {
				_me.changeTab(first);
			}
		}

		/*
		* Public Methods
		*/

		/*
		* changeTab
		* 
		* @param	alias
		*/
		this.changeTab = function (alias) {

			var current = _tabs[alias];
			var previous = _current;
			_current = current;

			if (previous) {
				// Remove selected class from the previous tab.
				previous.element.removeClass(_settings.classSelected);

				// Hide previous content.
				previous.content.hide();
			}

			// Add selected class to the current tab.
			current.element.addClass(_settings.classSelected);

			// Show current content. 
			current.content.show();
		};


		init();
		return this;
	};

	$.fn.carouselize = function (settings) {

		if (this.size() > 0) {

			// this == carousel element - to which applied this functionality
			var carousel = this;

			this.settings = {
				"leftArrow": ".arr-left",
				"rightArrow": ".arr-right"
			};
			$.extend(this.settings, settings);

			// dom elements
			this.container = carousel.find('.images');
			this.images = carousel.find('img');

			// sizes
			this.image = {
				width: 212
			};
			this.size = this.images.size();
			this.container.css("width", (this.size * this.image.width) + "px");

			this.current = 1;

			this.button = {

				right: carousel.find('.arr-right'),
				left: carousel.find('.arr-left'),

				update: function () {

					if (carousel.current == 1) {

						carousel.button.left.addClass("disabled");
					}
					else if (carousel.current == carousel.size) {

						carousel.button.right.addClass("disabled");
					}
					else {

						var disabled = carousel.find(".disabled");

						if (disabled) {

							disabled.removeClass("disabled");
						}
					}
				}
			};

			this.button.update();

			if (this.size > 1) {

				// Create bullets elemnt
				var bullets = $("<ul />").attr({
					"id": "bullets"
				});

				carousel.append(bullets);

				for (i = 0; i < this.size; i++) {
					bullets.append($("<li />"));
				}

				var currentBullet = bullets.find('li').first();
				currentBullet.addClass("current");
			}

			this.right = function () {

				if (carousel.current < carousel.size) {

					//carousel.container.anim({translateX: '-'+ carousel.image.width * carousel.current +'px'}, 0.25, 'linear');
					var moveBy = carousel.image.width * carousel.current;					
					//carousel.container.css("-webkit-transform", "translateX(-" + moveBy + "px)");
					carousel.container.css("left", "-" + moveBy + "px");
					carousel.current++;

					currentBullet.removeClass("current");
					currentBullet = currentBullet.next();
					currentBullet.addClass("current");
				}

				carousel.button.update();

			};

			this.left = function () {

				if (carousel.current > 1) {

					carousel.current--;
					//carousel.container.anim({translateX: '-'+ carousel.image.width * (carousel.current-1) +'px'}, 0.25, 'linear');
					var moveBy = carousel.image.width * (carousel.current - 1);
					//carousel.container.css("-webkit-transform", "translateX(-" + moveBy + "px)");
					carousel.container.css("left", "-" + moveBy + "px");
					currentBullet.removeClass("current");
					currentBullet = currentBullet.prev();
					currentBullet.addClass("current");
				}

				carousel.button.update();
			};

			if (this.size > 1) {

				this.button.right.bind("click", this.right);
				this.button.left.bind("click", this.left);
			}

			else {

				this.button.right.hide();
				this.button.left.hide();
			}

		} //end of if the carousel exist
	};
	
	$.fn.moreButton = function (options) {

        // Defaults:
        var settings = {
			BOX_LIST: "",
			HIDE_REACHED_TOTAL: "",
			CLASS_IS_BUTTON: "is-button",
			MAXIMUM_MORE_ITEMS: 40, // Maximum number of items to display when clicking a more button.
			MORE_ITEMS_IN_PAGE :10, // How many items to retrieve when clicking a more button.
			TYPE_SINGLE: "type-single", // More button can only operate once.
			TYPE_MULTIPLE: "type-multiple" // More button operates multiple times.
        };
		
		var HAS_TAP = (typeof ($.os.version) !== "undefined");
		//var EVENT_CLICK = HAS_TAP ? "tap" : "click";
		var EVENT_CLICK = "click";
		
		/**********************************************************************************************
		BUTTON ANIMATION
		**********************************************************************************************/

		/*	General controller for animation toggled by buttons.
		Receives a button instance and sets it up to animate it's defined container
		upon firing the click/tap event on the button. */
		function initAnimButton(button) {       

			/*	Perform logic before the event is bound */
			button.init();

			$(button.selector).bind(EVENT_CLICK, function (evt) {
				/*	Prevent default actions such as going to a link */
				
				evt.preventDefault();
				evt.stopPropagation();
				/*	Execute default actions for the event, BEFORE open/close logic */
				button.start();

				/*	Execute actions based on the state of the button */
				if (button.isOpen) {
					button.close();
				} else {
					button.open();
				}

				/*	Execute default actions for the event, AFTER open/close logic */
				button.end();			
			});
		}	

		/*	Setup the More-Buttons to open/close additional items upon click/tap */
		function initMoreButtons(buttons, hidden, type) {
			$(buttons).each(function (index, button) {
				var mb = new MoreButton(button, hidden, type);
				initAnimButton(mb);
			});
		}
		
		/**********************************************************************************************
		CLASS BUTTON
		The base class for buttons which open/close containers
		**********************************************************************************************/

		function Button(selector, containerSelector, isOpen, closeText) {
			this.selector = selector;
			this.containerSelector = containerSelector;

			/*	Tells us the state of the container */
			this.isOpen = isOpen || false;

			/*	Text to display when the container is opened */
			this.closeText = closeText || "סגור";

			/*	A class that will be added to the container when it is opened */
			this.openClass = "slideDown";

			/*	Cache references to Zepto.js objects */
			this.$button = $(selector);
			this.$container = $(containerSelector);

			/*	The original text of the button that will be restored when
			the container is closed after it's opened. */
			this.originalText = this.$button.html();
		}

		Button.prototype.init = function () {
			/*	Add a special class to all of the buttons, so the global click/tap handler
			would know that a button was clicked/tapped and not a regular element. */
			this.$button.addClass(settings.CLASS_IS_BUTTON);
		};

		/*	Define base methods */
		Button.prototype.start = function () { };
		Button.prototype.end = function () { };
		Button.prototype.open = function () { };
		Button.prototype.close = function () { };
		
		
		/**********************************************************************************************
		CLASS MORE-BUTTON
		Defines the behaviour of the buttons which are used to open/close more items
		of their defined container.
		**********************************************************************************************/

		MoreButton.prototype = new Button();

		function MoreButton(selector, hiddenSelector, type) {
			this.constructor.call(this, selector, selector);

			/*	Define new properties */
			this.$boxList = $(settings.BOX_LIST);
			this.$text = this.$button.find(".more-text");
			this.$play = this.$button.find(".play");
			this.originalHeight = 0;
			this.hiddenSelector = hiddenSelector;
			this.type = type;

			/*	Override Button's */
			this.$container = this.$boxList.find("ul");

			/*  Handle retrieving more items multiple times. */
			if (this.type === settings.TYPE_MULTIPLE) {
				var totalResults = parseInt(this.$boxList.find(".totalResults").val());
				this.totalResults = Math.min(totalResults, settings.MAXIMUM_MORE_ITEMS);
				this.pageSize = settings.MORE_ITEMS_IN_PAGE;
				this.currentPage = 1; // First request must always be for page no. 1.
				this.initialResults = this.$container.find("LI").length;
			}
		}


		/**********************************************************************************************
		CLASS MORE-BUTTON: OVERRIDE PARENT METHODS
		**********************************************************************************************/

		MoreButton.prototype.open = function () {
			var self = this;
			var url = this.$button.attr("href");

			if (this.type === settings.TYPE_MULTIPLE) {
				url += "&page=" + this.currentPage + "&pageSize=" + this.pageSize;
			}

			/*	AJAX CALL */
			$.get(
				url,

				function (data) {
					/*	Append the new items to container
						First "quarantine" them: append hidden to the DOM, add a CSS Class to mark them as new items
						and then append to the right place and remove the "quarantine" */
					self.$container.append('<li id="quarantine" style="display:none;"><ul></ul></li>');
					var $quarantine = self.$container.find("#quarantine > UL");
					$quarantine.append(data);
					$quarantine.find("LI").each(function(index, element) {
						$(element).addClass("more");
						self.$container.append(element);
					});
					$quarantine.remove();

					/*	Animate to new height */
					var moreHeight = self.findNewHeight();
					var currentHeight = self.$container.height();
					self.animateOpen(currentHeight, moreHeight);

					if (self.type === settings.TYPE_SINGLE) {
						/*  Change button state */
						self.changeState(true, currentHeight);
					}
					else if (self.type === settings.TYPE_MULTIPLE) {
						/*  Increment page counter */
						self.currentPage++;

						/*  Calculate if reached total results */
						var reachedTotal = (self.currentPage - 1) * self.pageSize + self.initialResults >= self.totalResults;
						if (reachedTotal) {
							// hide 'more' button.
							self.$button.hide();
							$(settings.HIDE_REACHED_TOTAL).hide();
						}
					}
				}
			);
		};

		MoreButton.prototype.close = function () {
			if (this.type === settings.TYPE_SINGLE) {
				/*	Remove items and class */
				this.$container.removeClass(this.openClass);
				this.$container.find(this.hiddenSelector).remove();

				/*	Animate to previous height */
				this.$container.css("height", this.originalHeight + "px");

				/*	Clean-up old animation properties for the next one */
				var self = this;
				setTimeout(function () {
					self.$container.attr("style", "");
				}, 1000);

				/*	Change button state*/
				this.changeState(false);
			}
		};


		/**********************************************************************************************
		CLASS MORE-BUTTON: DEFINE OWN HELPER METHODS
		**********************************************************************************************/

		/*	Animate the container to show more items */
		MoreButton.prototype.animateOpen = function (currentHeight, moreHeight) {
			var self = this;

			/*	MUST preserve this sequence/delays:
			1. Explicitly set the container's height
			2. After some delay set the transition 
			3. After some delay set the NEW height and start the transition
			4. After TRANSITION DURATION add a class to state container is opened */
			this.$container.css("height", currentHeight + "px");
			setTimeout(function () {
				self.$container.css({ "-webkit-transition": "all 1s ease" });
			}, 1);

			setTimeout(function () {
				self.$container.css("height", (currentHeight + moreHeight) + "px");
			}, 2);

			setTimeout(function () {
				self.$container.addClass(self.openClass);
			}, 500);

			// Cleanup when the animation ended, and prepate for next time!
			if (this.type == settings.TYPE_MULTIPLE) {
				setTimeout(function () {
					self.$container.find("LI.more").removeClass("more");
					self.$container.removeClass(self.openClass);
					self.$container.attr("style", "");
				}, 500);
			}
		};

		/*	Change the state of the button when opening/closing it's container */
		MoreButton.prototype.changeState = function (isOpen, currentHeight) {
			if (this.type == settings.TYPE_MULTIPLE) {
				return;
			}

			if (isOpen) {
				this.isOpen = true;
				this.originalText = this.$text.html();
				this.originalHeight = currentHeight;
				this.$text.html(this.closeText);
				this.$play.css("-webkit-transform", "rotate(180deg)");
			} else {
				this.isOpen = false;
				this.$text.html(this.originalText);
				this.$play.css("-webkit-transform", "rotate(0deg)");
			}
		};

		/*	Find new height by cloning and getting the height delta of new items */
		MoreButton.prototype.findNewHeight = function () {
			/*	Clone the container and append it after the real container */
			var $clone = $(this.$container.get(0).cloneNode(true));
			this.$container.after($clone.get(0));

			/*	Visually hide the clone */
			$clone.css({
				position: "absolute",
				visibility: "hidden"
			});

			/*	Expand the additional items */
			$clone.find(this.hiddenSelector).css({ height: "auto" });

			/*	Calc the new height */
			var newHeight = $clone.height() - this.$container.height();

			/*	Remove the clone */
			$clone.remove();
			return newHeight;
		};

		// Plugin code, return jQuery collection
        return this.each(function () {
            
			if (options) {
                $.extend(settings, options);
            }
			
			var $button = $(this);
			var buttonType = $button.hasClass(settings.TYPE_MULTIPLE) ? settings.TYPE_MULTIPLE : settings.TYPE_SINGLE;
			initMoreButtons(this, ".more", buttonType);

        }); // return

    }; // zoomer

})(window.Zepto);		